﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML><HEAD><TITLE>PostMessage/SendMessage Tutorial</TITLE>
<META http-equiv=Content-Type content="text/html; charset=UTF-8"><LINK 
href="../css/default.css" type=text/css rel=stylesheet><LINK media=print 
href="../css/print.css" type=text/css rel=stylesheet>
<META content="MSHTML 6.00.6000.16705" name=GENERATOR></HEAD>
<BODY>
<H1>向窗口或者窗口控件发送消息，作者：Rajat</H1>


<P>本页讨论 <A href="../commands/PostMessage.htm">PostMessage</A>&nbsp;和 <A 
href="../commands/PostMessage.htm">SendMessage</A>&nbsp;命令，并将回答这样一些问题：</P>
<P>“我如何按下已被最小化的窗口中的按钮？”<BR>“当 <A 
href="../commands/WinMenuSelectItem.htm">WinMenuSelectItem</A> 
不起作用时，我如何选中一个菜单项？！”<BR>“这是个可更换皮肤的窗口……如何保证我发送的命令每次都能生效？”<BR>“<SPAN 
style="FONT-WEIGHT: bold">隐藏</SPAN>窗口的话该怎么办？！”<BR><BR><BR>环境要求：AutoHotkey 
v1.0.09+&nbsp;以及 Winspector Spy (<A 
href="http://www.windows-spy.com">www.windows-spy.com</A>)</P>
<P>例如第一个例子中，注意 <A href="../commands/WinMenuSelectItem.htm">WinMenuSelectItem</A> 
命令就对 Outlook Express 的"New Message"窗口上的菜单栏无效。换言之，该代码不起任何作用：</P>
<P><EM>WinMenuSelectItem, New Message,, &amp;Insert, &amp;Picture...</EM></P>
<P>&nbsp;</P>
<P>但 <A href="../commands/PostMessage.htm">PostMessage</A> 命令就能完成这个工作：</P>
<P><EM>PostMessage, 0x111, 40239, 0, , New Message</EM></P>
<P>好神奇啊！但那是啥鬼东西？0x111 是 <A href="SendMessageList.htm">wm_command 消息</A> 
的十六进制代码，40239 是让这个特殊的窗口理解为选择 'Insert Picture' 菜单项的代码。现在让我来告诉你如何获得一个类似 40239 
这样的值：</P>
<OL>
  <LI>启动 Winspector Spy 软件，打开 "New Message" 窗口。 
  <LI>拖动 Winspector Spy 窗口中的十字光标到 "New Message" 窗口的标题栏上(未被 Winspector Spy 
  窗口的覆盖效果遮蔽的部分)。 
  <LI>在左边列表中被选中的窗口名称上点击右键，选择 'Messages'。 
  <LI>右键点击空白窗口并选择 'Edit message filter'。&nbsp; 
  <LI>按 'filter all' 按钮，然后双击左边列表中的 'wm_command' 项。这样你将只监视此消息。 
  <LI>现在转到 "New Message" 窗口并从菜单栏选择:Insert &gt; Picture 。 
  <LI>返回 Winspector Spy 并按下信号灯按钮来暂停监视。 
  <LI>展开收集到的 wm_command 消息(忽略其它消息)。 
  <LI>你想要找的(通常)是一个代码为&nbsp;0 的消息。有时那里描述为 'win activated' 或者 'win destroyed' 
  以及其它等等……都是不需要的内容。你要是发现那有一个描述为 'Control ID: 40239' 的消息……那就是它了！ 
  <LI>现在将它放入上面的命令中你就搞定了！它就是 wParam 参数的值。 </LI></OL>
<P>在下一个例子中，我会用到画图，因为大概每个人都会有。现在，让我们假设你要使用 AutoHotkey 
从一个程序的工具栏选择一个工具；假设选择的就是取色这个工具。</P>
<P>你会怎么做？很可能是在工具栏按钮上用鼠标点击，对吧？但是工具栏可以被移动或者隐藏！在画图中也可以。所以如果目标用户移动或隐藏了工具栏，那么你的脚本在那个点上将会失效。但是下面的命令仍将有效：</P>
<P><EM>PostMessage, 0x111, 639,,,未命名 - 画图</EM></P>
<P><A href="../commands/PostMessage.htm">PostMessage</A> 
的另一个好处是窗口可以处在后台；相比之下，发送鼠标击键需要窗口处于激活状态。<BR><BR><BR>下面有更多的例子。注意：我用的是 WinXP Pro 
(SP1)……如果你使用的是不同的操作系统，那可能需要调整下参数(仅对于像写字板和记事本这种 windows 
自带的应用程序；其它的程序而言参数应该不用改变)。</P>
<P><SPAN class=CodeCom>;写字板字体设为青色</SPAN><BR><A 
href="../commands/PostMessage.htm">PostMessage</A>, 0x111, 32788, 0, ,文档 - 
写字板</P>
<P><SPAN class=CodeCom>;在记事本</SPAN><SPAN class=CodeCom>打开</SPAN><SPAN 
class=CodeCom>关于对话框</SPAN><BR><A 
href="../commands/PostMessage.htm">PostMessage</A>, 0x111, 65, 0, ,无标题 - 记事本</P>
<P><SPAN class=CodeCom>;在记事本</SPAN><SPAN class=CodeCom>切换</SPAN><SPAN 
class=CodeCom>自动换行</SPAN><BR><A 
href="../commands/PostMessage.htm">PostMessage</A>, 0x111, 32, 0, ,无标题 - 记事本</P>
<P><SPAN class=CodeCom>;播放/暂停 Windows Media Player </SPAN><BR><A 
href="../commands/PostMessage.htm">PostMessage</A>, 0x111, 32808, 0, , Windows 
Media Player </P>
<P><SPAN class=CodeCom>;挂起一个正在运行的AHK脚本的热键</SPAN><BR>DetectHiddenWindows, 
on<BR>SetTitleMatchMode, 2<BR>PostMessage, 0x111, 65305,,, MyScript.ahk - 
AutoHotkey <SPAN class=CodeCom>;对比挂起操作，使用 65306 来暂停脚本。</SPAN><BR><BR><BR>上文讲的是 
PostMessage 命令。<A href="../commands/PostMessage.htm">SendMessage</A> 
命令与之相同，此外还等待一个消息返回值。可以用作例如获取 Winamp 中当前播放的曲目(请看 <A href="Winamp.htm">Automating 
Winamp</A> 里的例子)。<BR></P>
<P>这里还有些注意事项：</P>
<UL>
  <LI>上文也提到了操作系统是 XP 
  并且要谨记消息值随着不同的操作系统而改变。如果你发现一个消息可以在你的系统上使用(对一个软件的某个版本)，那么它肯定也能用同样版本的软件在其它系统上使用。此外，大多数应用程序即使在不同的版本中也保持相同的消息值(例如 
  Windows Media Player&nbsp;和 Winamp)。 
  <LI>如果你已在 Winspector Spy 设置了过滤仅显示 wm_command 
  消息，而你仍然获得大量的消息,这时，在那消息上点右键选择&nbsp;hide (消息名称)……你不会想要看到那个不是你与目标软件交互而出现的消息。 
  <LI>在 Winspector Spy 中向右的箭头显示消息值，模糊的向左的箭头显示返回值。返回值为 0，可默认安全地视为 'no error'(使用 
  SendMessage 命令，返回值将会在 <A href="ErrorLevel.htm">%ErrorLevel%</A>&nbsp;中)。 
  <LI>要给部分标题匹配的窗口传递消息，在脚本里加上这行：<BR>SetTitleMatchMode, 2 
  <LI>要给隐藏窗口传递消息，在脚本里加上这行：<BR>DetectHiddenWindows, On </LI></UL>
<P>注意：此技术对某些应用程序无效。我对 VB&nbsp;和 Delphi 编写的应用程序用时只能侥幸。此技术最适于 C, C++ 编写的应用程序。对于 
VB应用程序，同个命令的 'LParam' 参数在传递时总是变化。对于 Delphi&nbsp;应用程序……一些程序的GUI (用户图形界面)甚至不使用 
wm_command 。它大概使用了鼠标位置和点击。</P>
<P>去探索吧……要在 AutoHotkey 论坛分享你的经验哦。欢迎您反馈信息！</P>
<P>这个指南并不是为新手们准备的(没有冒犯的意思)，因为这些命令被认为是高级专题。所以如果读完本文，你还是摸不着头脑的话，请忘了它吧。</P>
<P>-Rajat</P>
</BODY></HTML>
